﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace NetFlux
{
    public enum ConnectionState { Working, Stopped, Indeterminate, Stop };
    public class ConnectionManager
    {
        public string LastError { get; private set; }

        int port;
        SANetworks network;
        Server destinationServer;
        TcpListener server;
        string msisdn = "66D9301FF717148DFF4B";
        string custom_net = null;
        bool msisdn_set = false;

        public ConnectionState State { get; private set; }

        public void AssignServer(Server serv)
        {
            this.destinationServer = serv;
        }

        public void SetNetwork(SANetworks network)
        {
            this.network = network;
        }
        public void SetDefaultMSISDN(string msi)
        {
            this.msisdn = msi;
            this.msisdn_set = true;
        }
        public void SetCustomNet(string cnet)
        {
            this.custom_net = cnet;
        }
        
        public ConnectionManager(int localPort, SANetworks network)
        {

            Log("NetFlux Version: " + System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString());
            Log("Current Directory: " + Environment.CurrentDirectory);
            Log("OS 64: " + Environment.Is64BitOperatingSystem);
            Log("Machine Name: " + Environment.MachineName);
            Log("User: " + Environment.UserName);
            Log("OS Version: " + Environment.OSVersion);
            Log("Processors: " + Environment.ProcessorCount);
            Log("CLR: " + Environment.Version);
            Log("Network: " + network.ToString());
            Log("UID: "+ Pwned.Info.GetUID());
            Log("Starting Connection Manager");
 
            this.port = localPort;
            this.network = network;
            
            this.State = ConnectionState.Indeterminate;
        }

        public void Reset()
        {
            this.State = ConnectionState.Stop;
            Thread.Sleep(2000);
            if(server != null)
                try
                {

                    server.Stop();
                }
                catch { }

            server = null;
            Thread.Sleep(2000);
            
            this.State = ConnectionState.Indeterminate;
            Thread.Sleep(2000);
            

        }
        
 

        static void WriteOut(string text, NetworkStream stream)
        {
            byte[] data = Encoding.ASCII.GetBytes(text);
            stream.Write(data, 0, data.Length);
        }

        public void Log(string line)
        {
            try
            {
                System.IO.File.AppendAllText(Constants.APP_LOG, DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString()+ "   " + line + "\r\n");
            }
            catch
            {
            }
        }


        private void SendData(string data)
        {
            TcpClient destination = new TcpClient(destinationServer.IP.ToString(), 80);

            NetworkStream destinationStream = destination.GetStream();
            byte[] vlive = Encoding.ASCII.GetBytes(data);
            destinationStream.Write(vlive, 0, vlive.Length);
            destinationStream.Flush();
            int i = destinationStream.ReadByte();
            if (i != 4)
            {
                byte[] msgBytes = new byte[4096];
                int r = destinationStream.Read(msgBytes, 0, msgBytes.Length);

                string msgTxt = (char)i + Encoding.ASCII.GetString(msgBytes, 0, r);
                msgTxt = msgTxt;

            }
            else
            {
            }
            destination.Close();
        }

        bool InitVodacom(out TcpClient destination, out NetworkStream destinationStream)
        {
            string pack1 = @"GET http://www.vodacom.co.za/personal/main/weboutoffunds/?url= HTTP/1.1
Host: www.vodacom.co.za
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

";
            string pack2 = @"GET http://www.vodacom.co.za/personal/main/weboutoffunds/?url=http%3A%2F%2Fwww.vodacom.co.za%2Fpersonal%2Fmain%2Fweboutoffunds%2F%3Furl=http%3A%2F%2Fwww.vodacom.co.za%2Fpersonal%2Fmain%2Fweboutoffunds%2F%3Furl= HTTP/1.1
Host: www.vodacom.co.za
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

";

            string pack3 = @"GET http://www.vodacom.co.za/personal/main/weboutoffunds/?url=http%3A%2F%2Fwww.vodacom.co.za%2Fpersonal%2Fmain%2Fweboutoffunds%2F%3Furl=http%3A%2F%2Fwww.vodacom.co.za%2Fpersonal%2Fmain%2Fweboutoffunds%2F%3Furl= HTTP/1.1
Host: www.vodacom.co.za
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

";
            SendData(pack1);
            SendData(pack2);
            SendData(pack3);

            destination = new TcpClient(destinationServer.IP.ToString(), 80);

            destinationStream = destination.GetStream();

            byte[] vlive = Encoding.ASCII.GetBytes(
                 @"GET http://www.vodacom.co.za/personal/main/weboutoffunds/?url= HTTP/1.1
Host: www.vodacom.co.za
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

");

            string dala = "sala";

            //byte[] vlive = Encoding.ASCII.GetBytes(GET.Replace("[MS]", msisdn));
            destinationStream.Write(vlive, 0, vlive.Length);
            destinationStream.Flush();

            int i = destinationStream.ReadByte();

            byte[] msgBytes = new byte[4096];
            int r = destinationStream.Read(msgBytes, 0, msgBytes.Length);

            string msgTxt = (char)i + Encoding.ASCII.GetString(msgBytes, 0, r);
            if (msgTxt.Contains("NetFlux"))
            {
                //Sweet success
                msgTxt = msgTxt;
                return true;
            }
            else
            {
                Log("8ta Error :" + msgTxt + "\r\n");
                destination.Close();
                return false;
            }

            




        }

        private void InitCustom(out TcpClient destination, out NetworkStream destinationStream)
        {          
            string[] data = File.ReadAllLines(custom_net);
            int port = int.Parse(data[0]);

            StringBuilder send_data = new StringBuilder();
            for (int i = 1; i < data.Length; i++)
                send_data.Append(data[i]);

            byte[] send_bytes = Encoding.ASCII.GetBytes(send_data.ToString());

            destination = new TcpClient(destinationServer.IP.ToString(), port);

            destinationStream = destination.GetStream();
            destinationStream.Write(send_bytes, 0, send_bytes.Length);

        }

        private void InitTelkom(out TcpClient destination, out NetworkStream destinationStream)
        {          

            destination = new TcpClient(destinationServer.IP.ToString(), 80);
          
            destinationStream = destination.GetStream();

            string GET = @"GET http://my.8ta.com/awan/ HTTP/1.1
Host: my.8ta.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
Proxy-Connection: keep-alive

";
#if aDEBUG
            GET = @"GET http://my.8ta.com/awan/oob/ooa?msisdn=66D93019FD161483F840 HTTP/1.1
Host: my.8ta.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
Proxy-Connection: keep-alive

";
#endif

                
            byte[] vlive = Encoding.ASCII.GetBytes(GET.Replace("[MS]", msisdn));
            destinationStream.Write(vlive, 0, vlive.Length);

            int i = destinationStream.ReadByte();
            if (i != 4)
            {
                byte[] msgBytes = new byte[4096];
                int r = destinationStream.Read(msgBytes, 0, msgBytes.Length);
                string msgTxt = (char)i + Encoding.ASCII.GetString(msgBytes, 0, r);
                Log("8ta Error :" + msgTxt + "\r\n");

            }
            else
            {
            }
        }

        private void InitTelkom_(out TcpClient destination, out NetworkStream destinationStream)
        {
            //http://my.8ta.com/awan/oob/ooa?msisdn=66D9301FF717148DFF4B 
            
            bool airtime = false;
            
            if(!msisdn_set)
            try
            {
                TcpClient cClient = new TcpClient("google.co.za", 80);
                NetworkStream stream = cClient.GetStream();

                string stuff = @"GET http://google.com/ HTTP/1.1
Host: google.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:7.0a2) Gecko/20110708 Firefox/7.0a2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive

";
                byte[] stuffdata = Encoding.ASCII.GetBytes(stuff);

                stream.Write(stuffdata, 0, stuffdata.Length);
                stream.Flush();

                byte[] rec = new byte[1024];
                stream.Read(rec, 0, rec.Length);
                string recStr = Encoding.ASCII.GetString(rec);

                string ascii = recStr;
                if (ascii.Contains("msisdn"))
                    airtime = true;
                if (airtime)
                {
                    msisdn = ascii.Substring(ascii.IndexOf("msisdn") + "msisdn".Length + 1, 20);
                }
                msisdn_set = true;
                Log("MSISDN: " + msisdn);
            }
            catch(Exception e)
            {
                Log(e.Message);
            }

            destination = new TcpClient(destinationServer.IP.ToString(), 80);

            destinationStream = destination.GetStream();

            string GET = @"GET http://my.8ta.com/awan/oob/ooa?msisdn=[MS] HTTP/1.1
Host: my.8ta.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
Proxy-Connection: keep-alive

";
            byte[] vlive = Encoding.ASCII.GetBytes(GET.Replace("[MS]",msisdn));
            destinationStream.Write(vlive, 0, vlive.Length);

            int i = destinationStream.ReadByte();
            if (i != 4)
            {
                byte[] msgBytes = new byte[4096];
                int r = destinationStream.Read(msgBytes, 0, msgBytes.Length);
                string msgTxt = (char)i +  Encoding.ASCII.GetString(msgBytes, 0, r);
                Log("8ta Error :" + msgTxt + "\r\n");
            }
        }

     /*   private void InitCustom(out TcpClient destination, out NetworkStream destinationStream)
        {
            destination = new TcpClient(destinationServer.IP.ToString(), 80);
            destinationStream = destination.GetStream();
            byte[] vlive = File.ReadAllBytes(Constants.CUSTOM_NETFILE);

            string txt = Encoding.ASCII.GetString(vlive);
            Log("Custom: " + txt + "\r\n");
            destinationStream.Write(vlive, 0, vlive.Length);

            if (txt.Contains("8ta"))
            {
                int i = destinationStream.ReadByte();
                if (i != 4)
                {
                    byte[] msgBytes = new byte[4096];
                    int r = destinationStream.Read(msgBytes, 0, msgBytes.Length);
                    string msgTxt = (char)i + Encoding.ASCII.GetString(msgBytes, 0, r);
                    Log("8ta Custom Error :" + msgTxt + "\r\n");
                }
            }

        }*/

        private void InitCellC(out TcpClient destination, out NetworkStream destinationStream)
        {
            destination = new TcpClient(destinationServer.IP.ToString(), 443);
            destinationStream = destination.GetStream();
        }

        private void InitVodacom_old(out TcpClient destination, out NetworkStream destinationStream)
        {
            destination = new TcpClient(Constants.VODACOM_PROXY, Constants.VODACOM_PROXYPORT);

            destinationStream = destination.GetStream();
            byte[] vlive = Encoding.ASCII.GetBytes(
                @"CONNECT " + destinationServer.IP.ToString() + @":443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0a2) Gecko/20110720 Firefox/7.0a2
Proxy-Connection: keep-alive
Host: 10.113.101.144.techno-flux.co.cc

");
        
            destinationStream.Write(vlive, 0, vlive.Length);
            destinationStream.Flush();
            byte[] response = new byte[2048];
            destinationStream.Read(response, 0, response.Length);
            destinationStream.Flush();
            Thread.Sleep(100);
        }
        private void InitDefault(out TcpClient destination, out NetworkStream destinationStream)
        {
            destination = new TcpClient(destinationServer.IP.ToString(), 443);

            destinationStream = destination.GetStream();
        }


        Thread listenThread;
        public void Start()
        {      
                //ST_START:
                try
                {
                    server.Stop();
                    server = null;
                }
                catch
                {
                }
                try
                {
                    server = new TcpListener(IPAddress.Parse(Constants.LOCALIP), port);
                    server.Start();
                }
                catch
                {
                    Log("E23: Could not open port on " + Constants.LOCALIP + ":"  + port + " Please restart the application");
                    try
                    {
                        foreach (System.Diagnostics.Process proc in System.Diagnostics.Process.GetProcessesByName("openvpn.exe"))
                        {
                            try
                            {
                                proc.Kill();
                            }
                            catch { }
                        }
                        foreach (System.Diagnostics.Process proc in System.Diagnostics.Process.GetProcessesByName("openvpn"))
                        {
                            try
                            {
                                proc.Kill();
                            }
                            catch { }
                        }
                    }
                    catch
                    {
                    }

                   throw new Exception("Could not open port");
                }
                
            
            Log("Starting new Thread. List  ening for incoming connections. Single thread");
            listenThread = new Thread(() =>
            {
                while (true)
                {
                    if (State == ConnectionState.Stop)
                        break;
                    TcpClient client = server.AcceptTcpClient();
                    Log("Accepting a new connection " + client.Client.RemoteEndPoint.ToString());
                    Log("Starting sub-thread for con nection");
                    new Thread(() =>
                    {
                        try
                        {
                            Log("|Server: " + destinationServer.IP.ToString());
                            Log("|Starting initialization sequence");
                            
                            TcpClient destination=null;

                            NetworkStream destinationStream=null;
                            if (State == ConnectionState.Stop)
                                return;
                            bool success = false;
                            switch (network)
                            {

                                case SANetworks.Vodacom:
                                    success=InitVodacom(out destination, out destinationStream);
                                    break;
                                case SANetworks.Telkom:
                                    InitTelkom_(out destination, out destinationStream);
                                    break;
                                case SANetworks.Cell_C:
                                    InitCellC(out destination, out destinationStream);
                                    break;
                                case SANetworks.General:
                                    InitDefault(out destination, out destinationStream);
                                    break;
                                case SANetworks.Custom:
                                    InitDefault(out destination, out destinationStream);
                                    break;
                                default:
                                    InitDefault(out destination, out destinationStream);
                                    break;
                            }
                            if (success)
                            {
                                NetworkStream clientStream = client.GetStream();
                                Pwned.Connection connection = new Pwned.Connection(clientStream, destinationStream);
                                Log("|Finished initialization sequence");
                                Log("|Running connection");
                                connection.Run();
                                //Clean up
                                Log("|Cleaning up connection");
                                destination.Close();
                                client.Close();
                                connection = null;
                                destinationStream = null;
                                clientStream = null;
                                Log("Connection closed");
                            }
                            
                            
                        }
                        catch (Exception e)
                        {
                            Log("Error cleaning up connection " + client.Client.RemoteEndPoint.ToString());
                            Log(e.Message);
                        }
                   }) { IsBackground = true }.Start();
                }

            }) { IsBackground = true };
            listenThread.Start();
            State = ConnectionState.Working;
        }

        public void Stop()
        {
            server.Stop();
            listenThread.Abort();
        }
        
    }
}
